//USER solver
//$Id: user_common.h 678 2011-02-27 18:14:42Z Oleg.Bulychov $
#pragma once

//__________________________________________________________________________________
#include "src/heo/include/console_color.h"
#include "src/heo/include/random.h"
#include "src/heo/include/stream_visitor.h"
#include "src/heo/include/xml_file.h"
#include "src/heo/include/optimization_direction.h"
#include "src/heo/include/solution.h"
#include "src/heo/include/stop_condition.h"
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
template<class E>
struct user_traits
{
    typedef E TEnvironment;
};
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
struct user_tag
{};
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
template<class T>
class user_solver
{
    DISALLOW_COPY_AND_ASSIGN(user_solver);
public:
    typedef typename T::TEnvironment TEnvironment;
    typedef solution<typename TEnvironment::TSolution, user_tag> TSolution;

    typedef typename TSolution::TDirection TDirection;
    typedef typename TSolution::TCostType  TCostType;
protected:
    TEnvironment*           env_;
    int                     rank_;
    random_generator          rnd_;
    TSolution               current_;
public:
    explicit user_solver(): env_(NULL),
        rank_(0),
        rnd_(0)
    {
    }

    static char const* get_Name() { return "user"; }
    static char const* get_Section() { return get_Name(); }

    template<class V>
    void accept(V& v)
    {
    }

    TEnvironment* get_Environment() const { return env_; }

    int get_Rank() const { return rank_; }

    random_generator& get_Rnd() { return rnd_; }

    void init(TEnvironment* env, int rank, int thread_id, bool debug_flag = false)
    {
        if (!env_)
        {
            env_ = env;
            rank_ = rank;
            rnd_.set_Thread_Id(thread_id);
            current_.init(env_, rnd_);
        }
        else
        {
            ASSERT_(env_ == env);
            ASSERT_(rank_ == rank);
        }
    }

    template<class TInOutSolution>
    void init_From_Pool(Solution_Pool<TInOutSolution>& pool)
    {
        if (pool.sol_list_.empty())
        {
            current_.init(env_, rnd_);
            current_.generate(env_, rnd_);
        }
        else
        {
            size_t idx = rank_ % pool.sol_list_.size();
            current_.assign(pool.sol_list_[idx]);
        }
        current_.evaluate(env_, rnd_);
    }

    int get_Debug_Level() const
    {
        int level = env_->debug_level_;
        return level;
    }

    TSolution& get_Current_Solution()
    {
        return current_;
    }

    TSolution& get_Best_Solution()
    {
        return current_;
    }

    virtual void user_Solve(Solution_Pool<typename TEnvironment::TSolution>& pool,
        typename TEnvironment::TStatistics& stat, int np)
    {
    }

    virtual TSolution const& get_Final_Solution()
    {
        return current_;
    }

};
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________

//EOF!
